package main

import (
	"bytes"
	"flag"
	"html/template"
	"io"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"os/exec"
	"strings"

	"net-printer/assets"

	"github.com/gin-gonic/gin"
)

var uploadsDir *string

func createUploadDir(uploadDir string) error {
	_, err := os.Stat(uploadDir)
	if err == nil {
		return nil
	}
	if !os.IsNotExist(err) {
		return err
	}
	return os.Mkdir(uploadDir, os.ModePerm)
}

// 加载由 go-assets-builder 嵌入的模板
func loadTemplate() (*template.Template, error) {
	t := template.New("")
	for name, file := range assets.Assets.Files {

		if file.IsDir() || !strings.HasSuffix(name, ".tmpl") {
			continue
		}
		h, err := ioutil.ReadAll(file)
		if err != nil {
			return nil, err
		}
		t, err = t.New(name).Parse(string(h))
		if err != nil {
			return nil, err
		}
	}
	return t, nil
}

func getIndexHandler(ctx *gin.Context) {
	ctx.HTML(http.StatusOK, "/views/index.tmpl", gin.H{})
}

func postIndexHandler(ctx *gin.Context) {
	file, _ := ctx.FormFile("file")
	var filename = *uploadsDir + "/" + file.Filename
	err := ctx.SaveUploadedFile(file, filename)
	if err != nil {
		gin.DefaultWriter.Write([]byte("上传失败：" + err.Error() + "\n"))
		ctx.HTML(http.StatusOK, "/views/index.tmpl", gin.H{
			"info":      "上传失败：" + err.Error(),
			"infoClass": "fail",
		})
		return
	}

	// 如果上传的是docx，转换为pdf
	if strings.HasSuffix(filename, ".docx") {
		cmd0 := exec.Command("unoconv", filename)
		cmd0.Run()
		filename = filename[0:len(filename)-4] + "pdf"
	}

	num := ctx.PostForm("num")
	cmd := exec.Command("lp", "-n", num, filename)

	var output bytes.Buffer
	cmd.Stdout = &output
	err = cmd.Run()
	if err != nil {
		gin.DefaultWriter.Write([]byte("打印失败：" + err.Error() + "\n"))
		ctx.HTML(http.StatusOK, "/views/index.tmpl", gin.H{
			"info":      "打印失败：" + err.Error(),
			"infoClass": "fail",
		})
		return
	}
	gin.DefaultWriter.Write([]byte("打印任务提交成功：" + filename + "\n"))
	ctx.HTML(http.StatusOK, "/views/index.tmpl", gin.H{
		"info":      "打印任务提交成功",
		"infoClass": "success",
	})
}

func main() {
	// 参数
	uploadsDir = flag.String("d", "./uploads", "上传文件的缓存目录")
	logPath := flag.String("l", "./net-printer.log", "日志文件")
	listenAddr := flag.String("h", ":9999", "服务启动地址")
	flag.Parse()

	// 缓存
	err := createUploadDir(*uploadsDir)
	if err != nil {
		log.Fatal("创建缓存目录失败：", err.Error())
	}

	// 日志
	f, err := os.Create(*logPath)
	if err != nil {
		log.Fatal("创建日志文件失败：", err.Error())
	}
	if os.Getenv("GIN_MODE") == "release" {
		gin.DefaultWriter = io.MultiWriter(f)
	} else {
		gin.DefaultWriter = io.MultiWriter(f, os.Stdout)
	}

	// 创建gin应用
	app := gin.Default()

	// 加载模板
	t, err := loadTemplate()
	if err != nil {
		log.Fatal("加载模板失败：", err.Error())
	}
	app.SetHTMLTemplate(t)

	// 路由
	app.GET("/", getIndexHandler)
	app.POST("/", postIndexHandler)

	// 启动服务
	app.Run(*listenAddr)
}
